#pragma once

#include <string>
#include <memory>
#include <set>
#include <unordered_map>
#include <functional>

namespace gcov
{
    /* 一个case的信息 */
    typedef struct _XmlCaseInfo
    {
        int caseID;              // case的id，从1开始顺序增长
        std::string caseInData;  // case的输入参数
        std::string useOnStatus; // 入力变数的数值
        std::string expected;    // 期待出力值
        std::string actual;      // 实际出力值
        std::string time;        // 测试耗时
        std::string name;        // case的名字，基本就是"case"+caseID的组合

    public:
        std::string toString() const;
    } XmlCaseInfo;

    typedef struct _XmlCaseInfoPtrCompare
    {
        inline bool operator()(const std::shared_ptr<_XmlCaseInfo> &a, const std::shared_ptr<_XmlCaseInfo> &b) const
        {
            return a->caseID < b->caseID;
        }
    } XmlCaseInfoPtrCompare;

    class XmlCaseInfoList : public std::set<std::shared_ptr<_XmlCaseInfo>, XmlCaseInfoPtrCompare>
    {
    public:
        void foreach (std::function<void(std::shared_ptr<_XmlCaseInfo> info)> func) const;

        std::shared_ptr<_XmlCaseInfo> get(int number) const;
    };

    /* 一套case的信息 */
    typedef struct _XmlInfo
    {
        int caseNumber;                   // 几个case
        std::string testsuiteName;        // 这个是test的名字
        
        std::string fileName;             // 这是文件名，不是全路径
        std::string defineOutputFileName; // 默认的输出文件名
        std::string className;            // 测试类名
        std::string funcName;             // 测试函数名
        std::string funcAllName;          // TBD: 测试函数全名

        XmlCaseInfoList caseInfoList;

        std::string funcInCount = "1";  // 函数输入参数个数
        std::string funcOutCount = "1"; // 函数输出参数个数

        _XmlInfo() : caseNumber(0) {}

        std::string toString() const;
    } XmlInfo;

    class XmlMap : public std::unordered_map<std::string, std::shared_ptr<gcov::XmlInfo>>
    {
    public:
        /* easy foreach */
        void foreach (std::function<void(std::string, std::shared_ptr<gcov::XmlInfo>)> func) const;
    };
} // namespace gcov
